package com.sita.tboard.hitchhike.helper;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.sita.bike.persistence.CcDriverEntity;
import com.sita.bike.rest.model.response.Reply;
import com.sita.bike.support.Constants;
import com.sita.bike.support.LocationController;
import com.sita.bike.utils.AccountUtils;
import com.sita.tboard.hitchhike.bean.Driver;
import com.sita.tboard.hitchhike.bean.SelectedAddress;
import com.sita.tboard.hitchhike.bean.TicketModel;
import com.sita.tboard.hitchhike.bean.TicketStatus;
import com.sita.tboard.hitchhike.listeners.OnBecomeDriverListener;
import com.sita.tboard.hitchhike.listeners.OnGetDriverInfoListener;
import com.sita.tboard.hitchhike.listeners.OnGetTicketsListener;
import com.sita.tboard.hitchhike.listeners.OnHitchhikeAcceptTripPlanListener;
import com.sita.tboard.hitchhike.listeners.OnHitchhikeCreateTripLanListener;
import com.sita.tboard.hitchhike.listeners.OnPayHitchhikeListener;
import com.sita.tboard.hitchhike.listeners.OnTicketStatusChangeListener;
import com.sita.tboard.hitchhike.rest.AcceptTripPlanRequest;
import com.sita.tboard.hitchhike.rest.AcceptTripPlanResponse;
import com.sita.tboard.hitchhike.rest.BecomeDriverRequest;
import com.sita.tboard.hitchhike.rest.ChangeTicketStatusRequest;
import com.sita.tboard.hitchhike.rest.GetDriverInfoResponse;
import com.sita.tboard.hitchhike.rest.GetTicketsRequest;
import com.sita.tboard.hitchhike.rest.GetTicketsResponse;
import com.sita.tboard.hitchhike.rest.PassengerCreateTripPlanRequest;
import com.sita.tboard.hitchhike.rest.PassengerCreateTripPlanResponse;
import com.sita.tboard.hitchhike.rest.PayTripPlanRequest;
import com.sita.tboard.hitchhike.rest.PayTripPlanResponse;
import com.squareup.okhttp.OkHttpClient;

import java.util.ArrayList;
import java.util.concurrent.TimeUnit;

import retrofit.Callback;
import retrofit.RequestInterceptor;
import retrofit.RestAdapter;
import retrofit.RetrofitError;
import retrofit.client.OkClient;
import retrofit.client.Response;
import retrofit.converter.GsonConverter;
import retrofit.http.Body;
import retrofit.http.GET;
import retrofit.http.POST;
import retrofit.http.Path;

/**
 * Created by xiaodong on 16/3/30.
 */
public enum HitchhikeNetworkHelper {
    INSTANCE;

    private HitchhikeService hitchhikeService;

    HitchhikeNetworkHelper() {
        initRestService();
    }

    private interface HitchhikeService {
        @POST("/roadtrust/v1/renttrips")
        void passengerCreateTrip(@Body PassengerCreateTripPlanRequest request, Callback<PassengerCreateTripPlanResponse> callback);

        @POST("/roadtrust/v1/renttrips/accept")
        void driverAccessTrip(@Body AcceptTripPlanRequest reqeust, Callback<AcceptTripPlanResponse> callback);

        @POST("/roadtrust/v1/renttrips/pay")
        void passengerPayTrip(@Body PayTripPlanRequest reqeust, Callback<PayTripPlanResponse> callback);

        @POST("/roadtrust/v1/drivers")
        void becomeDriver(@Body BecomeDriverRequest reqeust, Callback<Reply> callback);

        @POST("/roadtrust/v1/renttrip/list")
        void getTickets(@Body GetTicketsRequest request, Callback<GetTicketsResponse> callback);

        @GET("/roadtrust/v1/drivers/{driverId}")
        void getDriverInfo(@Path("driverId") String driverId, Callback<GetDriverInfoResponse> callback);

        @GET("/roadtrust/v1/drivers/{driverId}")
        GetDriverInfoResponse getDriverInfoSync(@Path("driverId") String driverId);

        @POST("/roadtrust/v1/renttrip/status")
        void changeTicketStatus(@Body ChangeTicketStatusRequest request, Callback<Reply> callback);
    }

    private void initRestService() {
        final OkHttpClient okHttpClient = new OkHttpClient();
        okHttpClient.setReadTimeout(60, TimeUnit.SECONDS);
        okHttpClient.setConnectTimeout(30, TimeUnit.SECONDS);
        okHttpClient.setWriteTimeout(120, TimeUnit.SECONDS);

        Gson gson = new GsonBuilder().enableComplexMapKeySerialization().serializeNulls()
                .create();

        RequestInterceptor restInterceptor = new RequestInterceptor() {
            @Override
            public void intercept(RequestFacade request) {
                request.addHeader("Content-Type", Constants.APPLICATION_JSON);
                request.addHeader("Accept", Constants.APPLICATION_JSON);
            }
        };

        RestAdapter restAdapter = new RestAdapter.Builder()
                .setLogLevel(RestAdapter.LogLevel.FULL)
                .setEndpoint(Constants.BASE_URI)
                .setConverter(new GsonConverter(gson))
                .setRequestInterceptor(restInterceptor)
                .setClient(new OkClient(okHttpClient))
                .build();

        hitchhikeService = restAdapter.create(HitchhikeService.class);
    }

    public void passengerCreateTrip(final SelectedAddress from, final SelectedAddress to,
                               final long departureTime, final OnHitchhikeCreateTripLanListener listener) {
        final String accountId = AccountUtils.getAccountID();
        PassengerCreateTripPlanRequest request = new PassengerCreateTripPlanRequest()
                .setAccountId(AccountUtils.getAccountID())
                .setStartLat(from.getLatitude()).setStartLng(from.getLongitude())
                .setEndLat(to.getLatitude()).setEndLng(to.getLongitude())
                .setFromaddress(from.getFullAddress())
                .setToaddress(to.getFullAddress())
                .setDepartureTime(departureTime);
        hitchhikeService.passengerCreateTrip(request, new Callback<PassengerCreateTripPlanResponse>() {
            @Override
            public void success(PassengerCreateTripPlanResponse resp, Response response) {
                TicketModel ticket = new TicketModel();
                ticket.id = resp.idStatus.getRentTripId();
                ticket.status = resp.idStatus.getStatus();
                ticket.customId = Long.valueOf(accountId);
                ticket.toaddress = to.getFullAddress();
                ticket.fromaddress = from.getFullAddress();
                ticket.orderDepartureTime = departureTime;
                ticket.startLat = from.getLatitude();
                ticket.startLng = from.getLongitude();
                ticket.endLat = to.getLatitude();
                ticket.endLng = to.getLongitude();

                listener.onSuccess(ticket);
            }

            @Override
            public void failure(RetrofitError error) {
                listener.onFailure(error);
            }
        });
    }

    public void driverAcceptTrip(final String rentTripId, final OnHitchhikeAcceptTripPlanListener listener) {
        double latitude = LocationController.getLastKnownLocation().getLatitude();
        double longitude = LocationController.getLastKnownLocation().getLongitude();
        AcceptTripPlanRequest request = new AcceptTripPlanRequest()
                .setAccountId(AccountUtils.getAccountID())
                .setRentTripId(rentTripId)
                .setLat(latitude).setLng(longitude);
        hitchhikeService.driverAccessTrip(request, new Callback<AcceptTripPlanResponse>() {
            @Override
            public void success(AcceptTripPlanResponse resp, Response response) {
                HitchhikePersistHelper.INSTANCE.updateDriverTicketStatus(Long.valueOf(rentTripId),
                        TicketStatus.getInstance().ACCEPTED);
                listener.onSuccess();
            }

            @Override
            public void failure(RetrofitError error) {
                listener.onFailure(error);
            }
        });
    }

    public void passengerPayTrip(final String rentTripId, float money, final OnPayHitchhikeListener listener) {
        PayTripPlanRequest request = new PayTripPlanRequest()
                .setAccountId(AccountUtils.getAccountID())
                .setRentTripId(rentTripId)
                .setMoney(money);
        hitchhikeService.passengerPayTrip(request, new Callback<PayTripPlanResponse>() {
            @Override
            public void success(PayTripPlanResponse resp, Response response) {
                HitchhikePersistHelper.INSTANCE.deletePassengerTicket(Long.valueOf(rentTripId));
                listener.onSuccess();
            }

            @Override
            public void failure(RetrofitError error) {
                listener.onFailure(error);
            }
        });
    }

    public void becomeDriver(final String vehicleBrand, final String vehicleNumber, final OnBecomeDriverListener listener) {
        BecomeDriverRequest request = new BecomeDriverRequest()
                .setAccountId(AccountUtils.getAccountID())
                .setVehicleBrand(vehicleBrand).setVehicleNumber(vehicleNumber);
        hitchhikeService.becomeDriver(request, new Callback<Reply>() {
            @Override
            public void success(Reply resp, Response response) {
                Driver driver = new Driver(Long.valueOf(AccountUtils.getAccountID()), vehicleBrand, vehicleNumber);
                HitchhikePersistHelper.INSTANCE.saveDriver(driver);
                listener.onSuccess();
            }

            @Override
            public void failure(RetrofitError error) {
                listener.onFailure(error);
            }
        });
    }

    public void getDriverUnfinishedTickets(final int page, int size, final OnGetTicketsListener listener) {
        GetTicketsRequest request = new GetTicketsRequest()
                .setKnightId(AccountUtils.getAccountID())
                .setStatus(TicketStatus.getInstance().getWaitingStatuses())
                .setPageNumber(String.valueOf(page)).setPageSize(String.valueOf(size));
        hitchhikeService.getTickets(request, new Callback<GetTicketsResponse>() {
            @Override
            public void success(GetTicketsResponse resp, Response response) {
                ArrayList<TicketModel> items = new ArrayList<TicketModel>(resp.data);
                if (items != null && !items.isEmpty()) {
                    HitchhikePersistHelper.INSTANCE.saveDriverTickets(items);
                } else {
                    if (page == 0) {
                        HitchhikePersistHelper.INSTANCE.deleteDriverTickets();
                    }
                }

                listener.onSuccess(items);
            }

            @Override
            public void failure(RetrofitError error) {
                listener.onFailure(error);
            }
        });
    }

    public void getDriverWaitingTickets(int page, int size, final OnGetTicketsListener listener) {
        GetTicketsRequest request = new GetTicketsRequest()
                .setKnightId(AccountUtils.getAccountID())
                .setStatus(TicketStatus.getInstance().getWaitingStatuses())
                .setPageNumber(String.valueOf(page))
                .setPageSize(String.valueOf(size));
        hitchhikeService.getTickets(request, new Callback<GetTicketsResponse>() {
            @Override
            public void success(GetTicketsResponse resp, Response response) {
                ArrayList<TicketModel> items = new ArrayList<TicketModel>(resp.data);
                listener.onSuccess(items);
            }

            @Override
            public void failure(RetrofitError error) {
                listener.onFailure(error);
            }
        });
    }

    public void getPassengerHistoryTickets(int page, int size, final OnGetTicketsListener listener) {
        GetTicketsRequest request = new GetTicketsRequest()
                .setCustomId(AccountUtils.getAccountID())
                .setStatus(TicketStatus.getInstance().getFinishedStatuses())
                .setPageNumber(String.valueOf(page)).setPageSize(String.valueOf(size));
        hitchhikeService.getTickets(request, new Callback<GetTicketsResponse>() {
            @Override
            public void success(GetTicketsResponse resp, Response response) {
                ArrayList<TicketModel> items = new ArrayList<TicketModel>(resp.data);
                listener.onSuccess(items);
            }

            @Override
            public void failure(RetrofitError error) {
                listener.onFailure(error);
            }
        });
    }

    public void getPassengerUnfinishedTickets(final int page, int size, final OnGetTicketsListener listener) {
        GetTicketsRequest request = new GetTicketsRequest()
                .setCustomId(AccountUtils.getAccountID())
                .setStatus(TicketStatus.getInstance().getUnFinishedStatuses())
                .setPageNumber(String.valueOf(page)).setPageSize(String.valueOf(size));
        hitchhikeService.getTickets(request, new Callback<GetTicketsResponse>() {
            @Override
            public void success(GetTicketsResponse resp, Response response) {
                ArrayList<TicketModel> items = new ArrayList<TicketModel>(resp.data);
                if (items != null && !items.isEmpty()) {
                    HitchhikePersistHelper.INSTANCE.savePassengerTickets(items);
                } else {
                    if (page == 0) {
                        HitchhikePersistHelper.INSTANCE.deletePassengerTickets();
                    }
                }
                listener.onSuccess(items);
            }

            @Override
            public void failure(RetrofitError error) {
                listener.onFailure(error);
            }
        });
    }

    public void getDriverHistoryTickets(int page, int size, final OnGetTicketsListener listener) {
        GetTicketsRequest request = new GetTicketsRequest()
                .setKnightId(AccountUtils.getAccountID())
                .setStatus(TicketStatus.getInstance().getFinishedStatuses())
                .setPageNumber(String.valueOf(page)).setPageSize(String.valueOf(size));
        hitchhikeService.getTickets(request, new Callback<GetTicketsResponse>() {
            @Override
            public void success(GetTicketsResponse resp, Response response) {
                ArrayList<TicketModel> items = new ArrayList<TicketModel>(resp.data);
                listener.onSuccess(items);
            }

            @Override
            public void failure(RetrofitError error) {
                listener.onFailure(error);
            }
        });
    }

    public Driver getDriver() {
        if (HitchhikePersistHelper.INSTANCE.isDriver()){
            return HitchhikePersistHelper.INSTANCE.getDriver();
        }
        return null;
    }

    public void getDriver(final OnGetDriverInfoListener listener) {
        Driver driver = getDriver();
        if (null != driver){
            listener.onSuccess(driver);
            return;
        }
        hitchhikeService.getDriverInfo(AccountUtils.getAccountID(), new Callback<GetDriverInfoResponse>() {
            @Override
            public void success(GetDriverInfoResponse resp, Response response) {
                if (null != resp.driver) {
                    Driver driver = resp.driver;
                    HitchhikePersistHelper.INSTANCE.saveDriver(driver);
                    listener.onSuccess(driver);
                } else {
                    listener.onSuccess(null);
                }
            }

            @Override
            public void failure(RetrofitError error) {
                listener.onFailure(error);
            }
        });

    }

    public void changeDriverTicketStatus(final Long ticketId, final int status, final OnTicketStatusChangeListener listener){
        ChangeTicketStatusRequest request = new ChangeTicketStatusRequest()
                .setRentTripId(ticketId).setStatus(status);
        hitchhikeService.changeTicketStatus(request, new Callback<Reply>() {
            @Override
            public void success(Reply reply, Response response) {
                HitchhikePersistHelper.INSTANCE.updateDriverTicketStatus(ticketId, status);
                listener.onSuccess();
            }

            @Override
            public void failure(RetrofitError error) {
                listener.onFailure(error);
            }
        });
    }

    public void cancelDriverTicket(final Long ticketId, final OnTicketStatusChangeListener listener){
        ChangeTicketStatusRequest request = new ChangeTicketStatusRequest()
                .setRentTripId(ticketId).setStatus(TicketStatus.getInstance().CANCELED);
        hitchhikeService.changeTicketStatus(request, new Callback<Reply>() {
            @Override
            public void success(Reply reply, Response response) {
                HitchhikePersistHelper.INSTANCE.deleteDriverTicket(ticketId);
                listener.onSuccess();
            }

            @Override
            public void failure(RetrofitError error) {
                listener.onFailure(error);
            }
        });
    }

    public void cancelPassengerTicket(final Long ticketId, final OnTicketStatusChangeListener listener){
        ChangeTicketStatusRequest request = new ChangeTicketStatusRequest()
                .setRentTripId(ticketId).setStatus(TicketStatus.getInstance().CANCELED);
        hitchhikeService.changeTicketStatus(request, new Callback<Reply>() {
            @Override
            public void success(Reply reply, Response response) {
                HitchhikePersistHelper.INSTANCE.deletePassengerTicket(ticketId);
                listener.onSuccess();
            }

            @Override
            public void failure(RetrofitError error) {
                listener.onFailure(error);
            }
        });
    }
}
